﻿// DataProcessingInstruction.cs
// Contains a class for a data processing instruction


namespace armsim
{
    /// <summary>
    /// Class for a Data Processing Instruction in the Arm Architecture
    /// </summary>
    public class DataProcessingInstruction : BaseInstruction
    {
        /// <summary>
        /// Specifies the kind of Data Processing instruction this is
        /// </summary>
        public uint Opcode { get; protected set; }

        /// <summary>
        /// Specifies whether the flags are to be set
        /// </summary>
        public uint S { get; protected set; }

        /// <summary>
        /// The first operand. Must be a register
        /// </summary>
        public uint Rn { get; protected set; }

        /// <summary>
        /// The destination operand. Must be a register. (Mov, and Mvn instructions are weird).
        /// </summary>
        public uint Rd { get; protected set; }

        /// <summary>
        /// The value in the final 12 bits. 
        /// </summary>
        public DPOperand2 Operand2 { get; protected set; }
    
        /// <summary>
        /// Initializes a new Data Processing Instruction.
        /// </summary>
        /// <param name="instruction">32bit value to be decoded</param>
        public DataProcessingInstruction(uint instruction) : base(instruction)
        {
            this.Opcode = VirtualMemory.ExtractBits(instruction, 21, 24);
            this.S = VirtualMemory.ExtractBits(instruction, 20, 20);
            this.Rn = VirtualMemory.ExtractBits(instruction, 16, 19);
            this.Rd = VirtualMemory.ExtractBits(instruction, 12, 15);

            var bit25 = VirtualMemory.ExtractBits(instruction, 25, 25);
            var bit4 = VirtualMemory.ExtractBits(instruction, 4, 4);
            
            if (bit25 == 1u)
            {
                this.Operand2 = new DPImmOperand2(instruction);
            } 
            else if (bit25 == 0u && bit4 == 0u)
            {
                this.Operand2 = new DPRegImmRegOperand2(instruction);
            } 
            else if (bit25 == 0u && bit4 == 1u)
            {
                this.Operand2 = new DPRegShiftRegOperand2(instruction);
            }


        }

        /// <summary>
        /// Converts the instruction to assemlby language if possible
        /// </summary>
        /// <param name="cpu">Virtual cpu to get info from</param>
        /// <returns>the assembly</returns>
        public override string ToAssembly(VirtualCPU cpu)
        {
            return base.ToAssembly(cpu);
        }

        /// <summary>
        /// Executes the instruction
        /// </summary>
        /// <param name="cpu">the cpu to execute in and put the values into</param>
        public override void Execute(VirtualCPU cpu)
        {
        }

    }
}
